const { ccclass, property, requireComponent, executeInEditMode } = cc._decorator;

@ccclass
@executeInEditMode()
@requireComponent(cc.RichText)
export default class richTxtHelper extends cc.Component {

    // 用于标记组件
    @property
    private _tag: number = 0
    @property
    get tag() { return this._tag; }
    set tag(value) { this._tag = Number(value) }

    // 用于添加描述
    @property
    private _desc: string = ''
    @property
    get desc() { return this._desc; }
    set desc(value) { this._desc = `${value}` }

    @property
    private _string: string = '[hello] [word]'
    @property
    get string() { return this._string; }
    set string(value) {
        this._string = value;
        this._stringCache = '';
        this._updateRichText();
    }

    @property
    private _count: number = 0
    @property
    get count() { return this._count; }

    @property
    private _bold: boolean = false
    @property
    get bold() { return this._bold; }
    set bold(value) {
        this._bold = value;
        this._updateRichText();
    }

    get color(): string {
        return this.node ? this.node.color.toHEX() : 'ffffff'
    }

    private _stringCache: string = '';
    private _colorCache: Map<number, string> = new Map();

    public setColor(index: number, color: cc.Color | string) {
        if (this.node.children.length === 0) {
            return;
        }

        let _clickParamCount = 0;
        let _clickHandlerCount = 0;

        if (color instanceof cc.Color) {
            color = color.toHEX();
        }

        for (let i = 0; i < this.node.children.length; i++) {
            const node = this.node.children[i];
            if (node instanceof cc.PrivateNode) {
                if (CC_DEBUG) {
                    if (typeof node['_clickParam'] !== 'undefined') _clickParamCount++;
                    if (typeof node['_clickHandler'] !== 'undefined') _clickHandlerCount++;
                }
                if (node['_clickHandler'] && node['_clickParam'] == index) {
                    // 只记录首次，目的是记录原始颜色
                    if (!this._colorCache.has(index)) {
                        this._colorCache.set(index, node.color.toHEX());
                    }
                    node.color = node.color.fromHEX(color);
                    if (node.getComponent(cc.LabelOutline)) {
                        node.getComponent(cc.LabelOutline).color = node.color;
                    }
                    return;
                }
            }
        }

        if (CC_DEBUG) {
            if (_clickParamCount !== this.count) {
                cc.error('cc.RichTxt下的子节点，已经没有_clickParam属性(记录param属性的)了，请重新适配')
            }
            if (_clickHandlerCount !== this.count) {
                cc.error('cc.RichTxt下的子节点，已经没有_clickHandler属性(记录点击触发的函数名)了，请重新适配')
            }
        }
    }

    public setAllColor(color: cc.Color | string) {
        for (let index = 0; index < this._count; index++) {
            this.setColor(index, color);
        }
    }

    public resetAllColor() {
        this._colorCache.forEach((colorHEX, index) => {
            this.setColor(index, colorHEX);
        })
        this._colorCache.clear();
    }

    private _rthHandler(event, index) {
        this.node.emit('richTxtClick', {
            index: index,
            tag: this.tag,
            desc: this.desc
        }, event);
    }

    private _split(str: string): string[] {
        if (!str) return [''];

        const strArr = [];
        let string = '';

        for (let index = 0; index < str.length; index++) {
            const s = str[index];
            if (s === '[') {
                string && strArr.push(string);
                string = '';
            }
            string += s;
            if (s === ']') {
                string && strArr.push(string);
                string = '';
            }
        }

        string && strArr.push(string);

        return strArr;
    }

    private _package(string: string): string {
        if (string === '<br/>') return string;

        if (string[0] === '[' && string[string.length - 1] === ']') {
            const index = this._count++;
            const word = string.slice(1, -1);
            return `<on click="_rthHandler" param="${index}">${word}</on>`;
        } else {
            return string;
        }
    }

    private _updateRichText() {
        if (!this._string) {
            this.getComponent(cc.RichText).string = '';
            return;
        }

        if (!this._stringCache) {
            this._count = 0;
            this._colorCache.clear();
            const wordArr = this._split(this._string);
            wordArr.forEach((word) => {
                this._stringCache += this._package(word);
            })
        }

        const string = `<color=#${this.color}>${this._stringCache}</color>`;
        if (this._bold) {
            // b标签在ipad上适配有问题，文字会放大很多(ccc版本：2.4.2)
            this.getComponent(cc.RichText).string = `<outline color=#${this.color} width=1>${string}</outline>`;
        } else {
            this.getComponent(cc.RichText).string = string;
        }
    }

    onEnable() {

    }
    onDisable() {

    }

    onLoad() {
        this.node.on('color-change', this._updateRichText, this);
        if (CC_EDITOR) this._updateRichText();
    }

    onDestroy() {

    }
}
